﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Perceiveit.Xml.Converters
{


    #region public class TimeSpanXConverter : XConverter<TimeSpan>

    public class TimeSpanXConverter : XConverter<TimeSpan>
    {
        protected bool TryParse(string value, out TimeSpan parsed)
        {
            if (value.StartsWith("P") || (value.Length > 1 && value.StartsWith("-P"))) //this is the XML Duration format
            {
                bool negative = value.StartsWith("-");
                int start = negative?2:1;
                int years = 0;
                int months = 0;
                int days = 0;
                int hrs = 0;
                int mins = 0;
                int secs = 0;
                StringBuilder sb = new StringBuilder();
                bool time = false;
                bool result = true;
                parsed = TimeSpan.Zero;
                int val;
                value = value.ToUpper();
                for (int i = start; i < value.Length; i++)
                {
                    char c = value[i];
                    if (char.IsNumber(c))
                        sb.Append(c);
                    else
                    {
                        if (c == 'T')
                        {
                            time = true;
                            sb.Length = 0;
                            continue;
                        }
                        if (sb.Length == 0)
                            continue;
                        if (!int.TryParse(sb.ToString(), out val))
                        {
                            result = false;
                            break;
                        }
                        sb.Length = 0;
                        switch (c)
                        {
                            case('Y'):
                                years = val;
                                break;
                            case('M'):
                                if(time)
                                    mins = val;
                                else
                                    months = val;
                                break;
                            case('D'):
                                days = val;
                                break;
                            case('H'):
                                hrs = val;
                                break;
                            case('S'):
                                secs = val;
                                break;
                            default:
                                return false;

                        }
                    }
                }
                if(result)
                {
                    if(years > 0 || months > 0)
                    {
                        
                        if(negative)
                        {
                            DateTime offset = DateTime.Now;
                            offset = offset.AddYears(-years);
                            offset = offset.AddMonths(-months);
                            TimeSpan ts = DateTime.Now.Subtract(offset);
                            days += ts.Days;
                        }
                        else
                        {
                            DateTime offset = DateTime.Now;
                            offset = offset.AddYears(years);
                            offset = offset.AddMonths(months);
                            TimeSpan ts = offset.Subtract(DateTime.Now);
                            days += ts.Days;
                        }
                    }
                    if(negative)
                    {
                        days = -days;
                        hrs = -hrs;
                        mins = -mins;
                        secs = -secs;
                    }
                    parsed = new TimeSpan(days,hrs,mins,secs);
                }
                return result;
            }
            else
                return TimeSpan.TryParse(value, out parsed);
        }
        public override TimeSpan FromString(string value)
        {
            TimeSpan v;
            if (string.IsNullOrEmpty(value) || !this.TryParse(value, out v))
                v = TimeSpan.Zero;

            return v;
        }

        public override string ToString(TimeSpan value)
        {
            StringBuilder sb = new StringBuilder();
            
            if(value.Ticks == 0)
                return string.Empty;

            int days = Math.Abs(value.Days);
            int hours = Math.Abs(value.Hours);
            int mins = Math.Abs(value.Minutes);
            int secs = Math.Abs(value.Seconds);

            
            if((days + hours + mins + secs) == 0)
                return string.Empty;

            if (value.TotalMilliseconds < 0)
                sb.Append("-");

            sb.Append("P");
            if (value.Days != 0)
            {
                sb.Append(days);
                sb.Append("D");
            }


            if ((hours + mins + secs) > 0)
            {
                sb.Append("T");
                if (value.Hours != 0)
                {
                    sb.Append(hours);
                    sb.Append("H");
                }
                if (value.Minutes != 0)
                {
                    sb.Append(mins);
                    sb.Append("M");
                }
                if (value.Seconds != 0)
                {
                    sb.Append(secs);
                    sb.Append("S");
                }
            }

            return sb.ToString();
        }
    }

    #endregion
}
